#include "hal_data.h"
#include <stdio.h>
#include "VL53L4CD_api.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
    if(p_args->event == UART_EVENT_TX_COMPLETE)
    {
        uart_send_complete_flag = true;
    }
}

#ifdef __GNUC__                                 //串口重定向
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
        err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
        if(FSP_SUCCESS != err) __BKPT();
        while(uart_send_complete_flag == false){}
        uart_send_complete_flag = false;
        return ch;
}

int _write(int fd,char *pBuffer,int size)
{
    for(int i=0;i<size;i++)
    {
        __io_putchar(*pBuffer++);
    }
    return size;
}

/* Callback function */
i2c_master_event_t i2c_event = I2C_MASTER_EVENT_ABORTED;
uint32_t  timeout_ms = 100000;
void sci_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
    i2c_event = I2C_MASTER_EVENT_ABORTED;
    if (NULL != p_args)
    {
        /* capture callback event for validating the i2c transfer event*/
        i2c_event = p_args->event;
    }
}


int status;
volatile int IntCount;
uint8_t p_data_ready;
uint16_t dev, sensor_id;
VL53L4CD_ResultsData_t results;     /* Results data from VL53L4CD */
VL53L4CD_Version_t sw_version;  /* Driver version */
void get_data_by_polling(Dev_t dev);

/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */

    /* Open the transfer instance with initial configuration. */
    err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
    assert(FSP_SUCCESS == err);
    printf("hello world!\n");

    /* Initialize the I2C module */
    err = R_SCI_I2C_Open(&g_i2c2_ctrl, &g_i2c2_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_02, BSP_IO_LEVEL_HIGH);

    dev = 0x52;
    status = VL53L4CD_GetSWVersion(&sw_version);
    printf("Starting VL53L4CD driver version %u.%u.%u\n",
            sw_version.major,
            sw_version.minor,
            sw_version.build);

    /* Check if VL53L4CD is connected. 0xebaa is the sensor id. */
    status = VL53L4CD_GetSensorId(dev, &sensor_id);
    if(status || (sensor_id != 0xebaa))
    {
        printf("VL53L4CD not detected\n");
        return status;
    }
    else
    {
        printf("vl53l4 id=0x%x\n",sensor_id);

    }


    status = VL53L4CD_SensorInit(dev);
    printf("ok!\n");

    printf("Ranging starts\n");
    status = VL53L4CD_StartRanging(dev);

    get_data_by_polling(dev);

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

void get_data_by_polling(Dev_t dev)
{
    VL53L4CD_Error status;
    VL53L4CD_ResultsData_t results;
    uint8_t data_ready = 0;

    while(1)
    {
        /* 检测数据是否准备好 */
        status = VL53L4CD_CheckForDataReady(dev, &data_ready);
        if(status != VL53L4CD_ERROR_NONE){
            printf("Error checking data ready: %d\n", status);
            continue;  // 出错则跳过本次循环
        }

        if(data_ready)
        {
            /* 获取测距结果 */
            status = VL53L4CD_GetResult(dev, &results);
            if(status == VL53L4CD_ERROR_NONE)
            {
                if(results.range_status == 0)  // 数据有效
                {
                    printf("Valid Data: Distance = %5u mm, Signal = %6u kcps/spad\n",
                        results.distance_mm,
                        results.signal_per_spad_kcps);
                }
                else  // 数据无效
                {
                    printf("Invalid Data! Range status: %u\n", results.range_status);
                }
            }
            else{
                printf("Error getting results: %d\n", status);
            }

            /* 清除中断以进行下一次测量（必需操作） */
            status = VL53L4CD_ClearInterrupt(dev);
            if(status != VL53L4CD_ERROR_NONE){
                printf("Error clearing interrupt: %d\n", status);
            }

        }else{
            /* 数据未准备好，稍作等待，减少CPU负载 */
            R_BSP_SoftwareDelay(5U, BSP_DELAY_UNITS_MILLISECONDS);
        }

        /* 可以在此处加入退出条件或停止机制（如检测外部标志位） */
    }
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);

#if BSP_CFG_SDRAM_ENABLED

        /* Setup SDRAM and initialize it. Must configure pins first. */
        R_BSP_SdramInit(true);
#endif
    }
}

#if BSP_TZ_SECURE_BUILD

FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
FSP_CPP_FOOTER

#endif
